/**
 * 实现白名单 + 全局守卫
 */
import { ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { AuthGuard } from '@nestjs/passport';
import { IS_PUBLIC_KEY } from './auth.decorator'

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(
    private reflector: Reflector
  ) {
    super();
  }

  canActivate(context: ExecutionContext) {
    const handler = context.getHandler();
    const controller = context.getClass();

    const isPublicMethod = this.reflector.get<boolean>(IS_PUBLIC_KEY, handler);
    const isPublicController = this.reflector.get<boolean>(IS_PUBLIC_KEY, controller);
    if (isPublicMethod || isPublicController) {
      return true;
    }

    return super.canActivate(context)
  }

  handleRequest(err, user, info) {
    /**
     * @info.name
     * JsonWebTokenError	token 格式错误（伪造）
     * TokenExpiredError	token 已过期
     * undefined	校验成功或没有错误
     */
    if (info?.name === 'JsonWebTokenError') {
      throw new UnauthorizedException('身份格式错误')
    }
    if (info?.name === 'TokenExpiredError') {
      throw new UnauthorizedException('登录已过期,请重新登录')
    }
    if (err || !user) {
      throw new UnauthorizedException('请先登录');
    }
    return user;
  }
}